// DSSocketClient.h: interface for the DSSocketClient class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_JSSOCKETCLIENT_H__FB35A9DF_A776_4FE0_8923_21D59A9988D8__INCLUDED_)
#define AFX_JSSOCKETCLIENT_H__FB35A9DF_A776_4FE0_8923_21D59A9988D8__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "remoting\Server.h"

using COM::CClientAgent;
using COM::socket_t;
//using namespace Amf;

class DSSocketClient;
typedef std::multimap<std::wstring, DSSocketClient*> EventMapType;
class RMT_CLASS_EXPORT DSSocketClient : public CClientAgent  
{
public:
	DSSocketClient();
	virtual ~DSSocketClient();

	// Event
	void EventRegist (LPCWSTR name);
	void EventRemove (LPCWSTR name);
	void EventUpdateList(Amf::AmfObjectPtr pNameList);
	static void EventDispatch (LPCWSTR name, Amf::AmfObjectPtr obj);
	static void EventGetRegisterList(LPCWSTR name, HT::StdPtrArray &Register);

	// Context
	static DSSocketClient* GetCurrentClient ();

protected:
	virtual void Run ();
	virtual void OnCancel ();
	
	bool IsBreak();

	bool SwitchRequest(DWORD dwLen,DWORD dwStrand,std::vector<unsigned char>& RecvAry);
	Amf::AmfArrayPtr DealwithClientRequest(Amf::AmfObjectPtr ReqObj);

	void OnRequest(unsigned char *data, uint32 len, void* head);
	Amf::AmfObjectPtr m_pClientInfo;
	std::wstring GetClientId ();

protected:
	void EventSendTo (LPCWSTR name, Amf::AmfObjectPtr obj);
	static void SetCurrentClient (DSSocketClient* pClient);
	static void ClearCurrentClientMap ();

private:
	void SendToClient (Amf::AmfArrayPtr obj, uint16 cmd, uint32 packet_counter);
	void EventClearRegister ();
	COM::mutex m_Mutex;
	bool m_bCancel;

	std::vector<std::wstring> m_EventList;
	static COM::mutex m_EventMutex;
	static COM::mutex m_ContextMutex;
	static EventMapType m_EventMap;
	static std::map<int32, DSSocketClient*> m_ClientInfoMap;
};

class RMT_CLASS_EXPORT DS_Except : public HT::Except
{
public:
	enum LEVEL_TYPE
	{
		LV_DEBUG,
		LV_INFO,
		LV_WARN,
		LV_ERROR,
		LV_FATAL,
	};

	DS_Except (int code, LEVEL_TYPE level = LV_DEBUG, LPCTSTR strWhat = NULL) : HT::Except(code, strWhat), m_nLevel(level)
	{ }
	LEVEL_TYPE GetLevel () { return m_nLevel; }

protected:
	LEVEL_TYPE m_nLevel;	// 0 DEBUG 1 INFO 2 WARN 3 ERROR 4 FATAL
};

#define HT_THROW_INFO(code,what) { std::stringstream str;	str << what;	throw DS_Except(code, DS_Except::LV_INFO, str.str().c_str()); }
#define HT_THROW_WARN(code,what) { std::stringstream str;	str << what;	throw DS_Except(code, DS_Except::LV_WARN, str.str().c_str()); }
#define HT_THROW_ERROR(code,what) { std::stringstream str;	str << what;	throw DS_Except(code, DS_Except::LV_ERROR, str.str().c_str()); }
#define HT_THROW_FATAL(code,what) { std::stringstream str;	str << what;	throw DS_Except(code, DS_Except::LV_FATAL, str.str().c_str()); }

#define HT_CHECK_INFO(condition,err_code,msg)	if(!(condition)) { HT_THROW_INFO(err_code,msg);}
#define HT_CHECK_WARN(condition,err_code,msg)	if(!(condition)) { HT_THROW_WARN(err_code,msg);}
#define HT_CHECK_ERROR(condition,err_code,msg)	if(!(condition)) { HT_THROW_ERROR(err_code,msg);}
#define HT_CHECK_FATAL(condition,err_code,msg)	if(!(condition)) { HT_THROW_FATAL(err_code,msg);}

#define HT_CHECK_RET(condition,ret) if (!(condition)){ return ret;}
#define HT_CHECK_RET_VOID(condition) if (!(condition)){ return;}
#define HT_CHECK(condition) if (!(condition)){HT_THROW_FATAL(HT_BASIC_ERR_UNKNOW,"Assert failed! FileName: " << __FILE__ << ",Line No.:" << __LINE__);}

#define HT_CHECK_ERR_OPERATION(condition,err_code,op,msg)	if(!(condition)) { op;HT_THROW_ERROR(err_code,msg);}

#define HT_CHECK_PARAM(condition,msg) HT_CHECK_ERROR(condition,HT_BASIC_ERR_PARAM_INVALID,msg)

#ifdef  NDEBUG
#define HT_ASSERT(condition)     ((void)0)
#else
#define HT_ASSERT(condition) \
	if(!(condition)) \
	HT_THROW_ERROR(HT_BASIC_ERR_UNKNOW,"assert failed! FileName: " << __FILE__ << ",Line No.: " << __LINE__)
#endif

#endif // !defined(AFX_JSSOCKETCLIENT_H__FB35A9DF_A776_4FE0_8923_21D59A9988D8__INCLUDED_)
